home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #45 (Jun 89) / Splitbar Test ƒ / MyScroll.Pas < prev    next >
Pascal/Delphi Source File  |  1989-03-28  |  7KB  |  227 lines

  1. unit MyScroll;
  2. interface
  3.     uses
  4.         MyGlobals;
  5.  
  6.     procedure AdjustScrollBars; {reset max of scroll bars}
  7.     procedure AdjustText (pane: integer); {scroll to scrollbar value}
  8.     procedure ScrollCharacter; {scroll selection into view}
  9.     procedure ScrollToSelection; { figure which way to scroll}
  10.     procedure SetEditText (Index: integer); {Switch EditText to proper pane}
  11.     procedure FixTextRects; {resize EditText's rectangles and recalculate line starts}
  12.     procedure FixScrollbarRects; {resize and postion scroll/split bars}
  13.     procedure UpdateOtherPane; {invalidate non active pane's update area}
  14.  
  15. implementation
  16.  
  17. { LinesInText is a kluge necessitated by a minor bug in TE. The bug is that if the last                 }
  18. { character in the TE text buffer is a Carriage Return, the field "nLines" may be off by one,        }
  19. { and cause slightly incorrect updating of the window. This routine always returns the}
  20. { correct number of lines in the buffer.     This is taken from Symantec's Think's Pascal}
  21.     function LinesInText: integer;
  22.         var
  23.             lines: integer;
  24.             txt: CharsHandle;
  25.     begin
  26.         with EditText^^ do
  27.             begin
  28.                 lines := nLines;
  29.                 txt := CharsHandle(hText);
  30.                 if teLength > 0 then
  31.                     if txt^^[teLength - 1] = CR then {Carriage Return?}
  32.                         lines := lines + 1;
  33.                 LinesInText := lines
  34.             end
  35.     end; {of LinesInText}
  36.  
  37.     procedure AdjustScrollBars; {reset max of scroll bars}
  38.         var
  39.             ctlMax, index, height: integer;
  40.     begin
  41.         for index := 1 to 2 do {for each pane}
  42.             begin
  43.                 SetEditText(index); {set pane}
  44.                 with EditText^^ do
  45.                     begin
  46.                         height := (viewRect.bottom - viewRect.top) div lineHeight; {lines of text in viewRect}
  47.                         ctlMax := LinesInText - height; {Control max}
  48.                         if ctlMax < 0 then
  49.                             ctlMax := 0;
  50.                         SetCtlMax(Scroll[index], ctlMax)
  51.                     end
  52.             end;
  53.         SetEditText(activePane); {reset EditText back to active pane}
  54.     end; {of AdjustScrollBars}
  55.  
  56.     procedure AdjustText; {scroll to scrollbar value}
  57.         var
  58.             oldScroll, newScroll, delta: integer;
  59.     begin
  60.         SetEditText(pane);
  61.         with EditText^^ do
  62.             begin
  63.                 oldScroll := viewRect.top - destrect.top; {get old scroll value}
  64.                 newScroll := GetCtlValue(Scroll[pane]) * lineHeight; {get new scroll value}
  65.                 delta := oldScroll - newScroll;
  66.                 if delta <> 0 then
  67.                     begin
  68.                         TEScroll(0, delta, EditText); {scroll to new value}
  69.                     end;
  70.             end;
  71.         destRect[pane] := EditText^^.destRect; {reset destRect for switching}
  72.         SetEditText(activepane); {reset to active pane}
  73.     end; {of AdjustText}
  74.  
  75.     procedure ScrollCharacter; {scroll selection into view}
  76.         var
  77.             theLine, height: integer;
  78.     begin
  79.         HLock(Handle(EditText));
  80.         theLine := 0;
  81.         with EditText^^ do
  82.             begin
  83.                 height := (viewRect.bottom - viewRect.top) div lineHeight;
  84.                 while selStart >= lineStarts[theLine] do
  85.                     theLine := theLine + 1;
  86.                 SetCtlValue(Scroll[activePane], theLine - nLines div 2);
  87.                 AdjustText(activePane);
  88.             end;
  89.         HUnLock(Handle(EditText));
  90.     end; {of scroll character}
  91.  
  92.     procedure ScrollToSelection; {Figure which way to scroll to get selection}
  93.         var
  94.             topline, bottomline, height, max: integer;
  95.     begin
  96.         SetEditText(activePane);
  97.         HLock(Handle(EditText));
  98.         AdjustScrollBars;
  99.         AdjustText(activePane);
  100.         with EditText^^, viewRect do
  101.             begin
  102.                 topline := GetCtlValue(Scroll[activePane]);
  103.                 height := (bottom - top) div lineHeight;
  104.                 bottomline := topline + height;
  105.                 max := GetCtlMax(Scroll[activePane]);
  106.                 if max = 0 then {all text within pane}
  107.                     AdjustText(activePane)
  108.                 else
  109.                     ScrollCharacter; {need to scroll}
  110.             end;
  111.         HUnLock(Handle(EditText));
  112.     end; {of ScrollToSelection}
  113.  
  114.     procedure SetEditText;
  115.   {Set EditText to indexed pane}
  116.     begin
  117.         EditText^^.viewRect := viewRect[Index];
  118.         EditText^^.destRect := destRect[Index];
  119.     end; {of SetEditText}
  120.  
  121.     procedure FixTextRects; {adjust EditText's two panes}
  122.     begin
  123.         HLock(Handle(EditText));
  124.         viewRect[1] := MyWindow^.portRect; {set lower pane}
  125.         viewRect[1].top := Split^^.contrlValue + IndicatorWidth;
  126.         viewRect[1].right := viewRect[1].right - SBarWidth;
  127.         viewRect[1].bottom := viewRect[1].bottom - SBarWidth;
  128.         InsetRect(viewRect[1], Margin, Margin); {Give TE margins}
  129.  
  130.     {Make viewRect a Multiple of lineHeight}
  131.         viewRect[1].bottom := viewRect[1].bottom - ((viewRect[1].bottom - viewRect[1].top) mod EditText^^.lineHeight);
  132.         destRect[1] := viewRect[1]; {Set destRect}
  133.  
  134.         viewRect[2] := MyWindow^.portRect; {set upper pane}
  135.         viewRect[2].bottom := Scroll[2]^^.contrlRect.bottom;
  136.         viewRect[2].right := viewRect[2].right - SBarWidth;
  137.         InsetRect(viewRect[2], Margin, Margin); {Give TE margins}
  138.  
  139.     {Make viewRect a multiple of lineHeight}
  140.         viewRect[2].bottom := viewRect[2].bottom - ((viewRect[2].bottom - viewRect[2].top) mod EditText^^.lineHeight);
  141.         destRect[2] := viewRect[2];
  142.  
  143.         SetEditText(activePane); {Reset EditText back to active pane}
  144.  
  145.         if EditText <> nil then {recalculate line starts}
  146.             begin
  147.                 TECalText(EditText);
  148.                 AdjustText(1);
  149.                 AdjustText(2);
  150.                 ScrollToSelection;
  151.             end;
  152.         HUnLock(Handle(EditText));
  153.     end; {of FixTextRects}
  154.  
  155.     procedure FixScrollbarRects; {adjust scrollbars according to splitbar}
  156.         var
  157.             width, hieght: integer;
  158.             temp: rect;
  159.     begin
  160.         with MyWindow^.portRect do {get window dimensions}
  161.             begin
  162.                 hieght := bottom - top - SBarWidth + 1;
  163.                 width := right - left - SBarWidth + 1;
  164.             end;
  165.  
  166.         SetRect(temp, width, 0, width + SBarWidth, hieght); {set control rectangles}
  167.         Split^^.contrlRect := temp;
  168.         Scroll[1]^^.contrlRect := Split^^.contrlRect;
  169.         Scroll[2]^^.contrlRect := Split^^.contrlRect;
  170.         Scroll[1]^^.contrlRect.top := Split^^.contrlValue + IndicatorWidth;
  171.         Scroll[2]^^.contrlRect.bottom := Split^^.contrlValue;
  172.  
  173.     {check to see if there is enough room to draw scroll bars}
  174.         if (Scroll[2]^^.contrlRect.bottom - Scroll[2]^^.contrlRect.top) < SBarMinLen then
  175.             begin {not enough room, make invisible}
  176.                 EraseRect(Scroll[2]^^.contrlRect);
  177.                 Scroll[2]^^.contrlVis := invisible;
  178.             end
  179.         else {enough room, make visible}
  180.             Scroll[2]^^.contrlVis := visible;
  181.  
  182.         if (Scroll[1]^^.contrlRect.bottom - Scroll[1]^^.contrlRect.top) < SBarMinLen then
  183.             begin {not enough room, make invisible}
  184.                 EraseRect(Scroll[1]^^.contrlRect);
  185.                 Scroll[1]^^.contrlVis := invisible;
  186.             end
  187.         else {enough room, make visible}
  188.             Scroll[1]^^.contrlVis := visible;
  189.  
  190.         if EditText <> nil then {fix TE rectangles}
  191.             begin
  192.                 FixTextRects;
  193.                 EraseRect(MyWindow^.portRect);
  194.                 InvalRect(MyWindow^.portRect);
  195.             end;
  196.     end;{ of FixScrollbarRects}
  197.  
  198.     procedure UpdateOtherPane; {invalidate non active pane for updating}
  199.         var
  200.             tempRect: array[1..2] of rect;
  201.             delta: array[1..2] of integer;
  202.             i, index: integer;
  203.             pane: rect;
  204.             intersect: boolean;
  205.     begin
  206.         case activePane of {get non active pane}
  207.             1: 
  208.                 index := 2;
  209.             2: 
  210.                 index := 1;
  211.         end;
  212.  
  213.         for i := 1 to 2 do {normalize viewRects to check for overlapp}
  214.             begin
  215.                 delta[i] := destRect[i].top;
  216.                 tempRect[i] := viewRect[i];
  217.                 OffsetRect(tempRect[i], 0, -delta[i]);
  218.             end;
  219.  
  220.         intersect := SectRect(tempRect[1], tempRect[2], pane); {get intersection}
  221.         OffsetRect(pane, 0, delta[index]); {place intersection to correct area on window}
  222.  
  223.         if intersect then {invalidate intersecting rectangle}
  224.             InvalRect(pane);
  225.     end; {of UpdateOtherPane}
  226.  
  227. end.